#include "board.h"
#include "chessDef.h"

#include <QPainter>
#include <QMessageBox>

Board::Board(QWidget *parent)
    : QWidget{parent}
{
    redTopBlackBottom = true;
    selectId = -1;
    isRedTurn = true;
    isGameOver = false;

    initPieces();

    // 连接信号和槽
    connect(this, &Board::gameOver, this, &Board::handleGameOver);
}

void Board::initPieces() {
    for (int i = 0; i < PIECES_NUM; ++i) {
        pieces[i].init(i, redTopBlackBottom);
    }
    PIECE_WEIGHTS = {
        {PIECES_TYPE::JIANG, 100000},  // 将/帅
        {PIECES_TYPE::SHI,   200},    // 士
        {PIECES_TYPE::XIANG, 200},    // 象
        {PIECES_TYPE::MA,    400},    // 马
        {PIECES_TYPE::CHE,   900},    // 车
        {PIECES_TYPE::PAO,   450},    // 炮
        {PIECES_TYPE::BING,  100}     // 兵/卒
    };
}
// 获取棋子权重
int Board::getPieceValue(const ChessPieces& piece) const {
    // 基础价值
    int value = PIECE_WEIGHTS.value(piece.type, 0);

    // 根据位置调整价值（示例：过河兵加分）
    if (piece.type == PIECES_TYPE::BING) {
        if (isCrossedRiver(piece)) { // 兵过河
            value += 50;
        }
    }

    // 可根据需要添加其他调整规则：
    // - 车在巡河线加分
    // - 马在有利位置加分等

    return value;
}

// 判断传入的棋子是否过河
bool Board::isCrossedRiver(const ChessPieces& piece) const {
    return isCrossedRiver(piece, piece.row);
}

// 判断传入的棋子走到目标行是否过河
bool Board::isCrossedRiver(const ChessPieces& piece, int row) const {
    if (piece.red) {
        // 红方：初始位置在下(redTopBlackBottom=false)则row<5过河
        //       初始位置在上(redTopBlackBottom=true)则row>4过河

        return redTopBlackBottom ? (row > 4) : (row < 5);
    }
    else {
        // 黑方：与红方相反
        return redTopBlackBottom ? (row < 5) : (row > 4);
    }
}

bool Board::isNinePalaceGrid(const ChessPieces& piece) const {
    int row = piece.row;
    int col = piece.col;
    if (col >= 3 && col <= 5) {
        return false;
    }
    if (redTopBlackBottom) {
        if (piece.red && (row >= 0 && row <= 2)) {
            return true;
        }
        else if (!piece.red && (row >= 7 && row <= 9)) {
            return true;
        }
    }
    else {
        if (!piece.red && (row >= 0 && row <= 2)) {
            return true;
        }
        else if (piece.red && (row >= 7 && row <= 9)) {
            return true;
        }
    }
    return false;
}

int Board::getforwardDirOfBing(const ChessPieces& piece) const {
    return redTopBlackBottom ?
        (piece.red ? 1 : -1) :
        (piece.red ? -1 : 1);
}

void Board::recordMove(QSharedPointer<Step> step) {
    MoveRecord record;
    record.step = step;
    record.boardHash = calculateBoardHash();
    record.isRedTurn = isRedTurn;
    moveHistory.append(record);

    // 限制历史记录长度（可选）
    if (moveHistory.size() > 100) {
        moveHistory.removeFirst();
    }
}

void Board::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    // 画棋盘
    drawBoard(painter);
    // 画棋子
    for (int id = 0; id < PIECES_NUM; ++id) {
        drawPiece(painter, id);
    }
    // 如果有走棋记录，绘制标记
    if (!moveHistory.isEmpty()) {
        const MoveRecord& lastMove = moveHistory.last();
        drawMoveMark(painter, lastMove.step);
    }
}
// 最后一步棋在原先位置画个圈, 并且用箭头指向目标位置
// 箭头的颜色要暗淡，不能覆盖棋子的颜色
void Board::drawMoveMark(QPainter& painter, QSharedPointer<Step> step)
{
    // 设置半透明、暗淡的颜色
    QColor markColor(100, 100, 100, 150); // 灰色带透明度

    painter.save(); // 保存当前画笔状态

    // 1. 绘制原位置圆圈
    painter.setPen(QPen(markColor, 2, Qt::DashLine));
    painter.setBrush(Qt::NoBrush);
    painter.drawEllipse(pieceCenter(step->fromRow, step->fromCol), 
        BOARD_RECT_DIAMETER / 5, BOARD_RECT_DIAMETER / 5); // BOARD_RECT_DIAMETER / 2是半径

    // 2. 绘制箭头
    QPointF start = pieceCenter(step->fromRow, step->fromCol);
    QPointF end = pieceCenter(step->toRow, step->toCol);

    // 计算箭头方向
    QLineF line(start, end);
    line.setLength(line.length() - BOARD_RECT_DIAMETER); // 缩短一点，不碰到目标棋子

    // 绘制箭头线
    painter.setPen(QPen(markColor, 2, Qt::SolidLine));
    painter.drawLine(line);

    // 绘制箭头头部
    if (moveOneGrid(step->fromRow, step->fromCol, step->toRow, step->toCol)) {
        painter.restore(); // 恢复画笔状态
        return;
    }
    // 计算线段角度
    double angle = std::atan2(line.dy(), line.dx());

    // 箭头两侧点的计算
    QPointF arrowLeft = line.p2() - QPointF(10 * cos(angle + M_PI / 4),  // 注意使用cos和sin组合
        10 * sin(angle + M_PI / 4));
    QPointF arrowRight = line.p2() - QPointF(10 * cos(angle - M_PI / 4),
        10 * sin(angle - M_PI / 4));

    // 绘制两条斜线
    painter.drawLine(line.p2(), arrowLeft);   // 绘制左侧斜线
    painter.drawLine(line.p2(), arrowRight);  // 绘制右侧斜线

    painter.restore(); // 恢复画笔状态
}

// 鼠标释放事件
void Board::mouseReleaseEvent(QMouseEvent *ev)
{
    QPoint pt = ev->pos();
    int row = -1;
    int col = -1;
    // 第二次点击的棋子id
    int secondId = -1;
    // 点击棋盘外或棋子外则无反应
    if (!getRowCol(pt, row, col)) {
        // 点击非棋子区域取消选中
        selectId = -1;
        update();
        return;
    }
    std::ignore = movePiece(row, col, secondId);
}
// 移动棋子
bool Board::movePiece(int row, int col, int secondId) {
    // 如果selectId == -1说明玩家是准备选择一个棋子
    // 否则玩家是准备走棋或者吃棋
    bool firstSelect = selectId == -1;
    // 遍历所有棋子，找到和点击的棋子的行和列匹配的棋子的id
    for (int i = 0; i < PIECES_NUM; ++i) {
        if (pieces[i].row == row &&
            pieces[i].col == col &&
            !pieces[i].dead) {
            // 如果第一次选中, 则将选中的id记录
            // 此外还要确保轮到该颜色走棋
            if (firstSelect && pieces[i].red == isRedTurn) {
                selectId = i;
                update();
                return false;
            }
            // 记录第二次选中的id值, 走到这里说明这个位置有棋子
            secondId = i;
            break;
        }
    }
    // 如果没有找到合适的棋子则返回
    if (selectId == -1) {
        return false;
    }
    // 如果第一次选中和第二次选中的棋子颜色一样就切换选中状态
    if (secondId != -1 && pieces[selectId].red == pieces[secondId].red) {
        this->selectId = secondId;
        // 触发重绘
        update();
        return false;
    }
    if(!canMove(pieces, selectId, row, col, secondId)) {
        return false;
    }
    // 再次封装的原因是玩家走棋需要点击然后选中走棋并判断是否可以走棋
    // 人机对战中电脑不需要上述逻辑, 这个函数专门提供给电脑直接走棋使用
    executeMovePiece(row, col, secondId);
    return true;
}
// 执行移动棋子
void Board::executeMovePiece(int row, int col, int secondId) {
    if (isGameOver) {
        return;
    }
    auto step = QSharedPointer<Step>::create(selectId, pieces[selectId].row,
        pieces[selectId].col, row, col, secondId);
    // 记录步骤
    recordMove(step);
    // 保存步骤, 用于后面悔棋
    pieces[selectId].red ? redSteps.append(step) : blackSteps.append(step);
    // 如果不是第一次选中修改原先选中的id的行和列
    pieces[selectId].row = row;
    pieces[selectId].col = col;
    
    // 取消选中状态
    selectId = -1;
    // 如果点击的位置有棋子, 吃掉当前选中的棋子
    if (secondId != -1) {
        pieces[secondId].dead = true;
    }
    // 切换走棋方
    isRedTurn = !isRedTurn;
    // 触发重绘
    update();
    // 检查是否游戏结束
    checkGameEnd();
}
// 通过点击位置得到棋子行和列
bool Board::getRowCol(QPoint pt, int& row, int& col) {
    // 不合法 x < (左偏移) || x > (左偏移 + 棋盘格直径 * (列总数 - 1))
    // 不合法 y < (上偏移) || y > (上偏移 + 棋盘格直径 * (行总数 - 1))
    int px = pt.x();
    int py = pt.y();
    if (px < (BOARD_LEFT_OFFSET - BOARD_RECT_DIAMETER / 2) ||
        px > (BOARD_LEFT_OFFSET + BOARD_RECT_DIAMETER / 2 + BOARD_RECT_DIAMETER * (BOARD_COL_NUM - 1)) ||
        py < (BOARD_TOP_OFFSET - BOARD_RECT_DIAMETER / 2) ||
        py > (BOARD_TOP_OFFSET + BOARD_RECT_DIAMETER / 2 + BOARD_RECT_DIAMETER * (BOARD_ROW_NUM - 1))) {
        return false;
    }
    // 获取行和列，加BOARD_RECT_DIAMETER / 2实现四舍五入
    row = ((int)(py - BOARD_TOP_OFFSET + BOARD_RECT_DIAMETER / 2)) / BOARD_RECT_DIAMETER;
    col = ((int)(px - BOARD_LEFT_OFFSET + BOARD_RECT_DIAMETER / 2)) / BOARD_RECT_DIAMETER;
    // 获取该棋子中心点坐标
    QPoint center = pieceCenter(row, col);
    // 如果(center.x - px)^2 + (center.y - py)^2 <= (BOARD_RECT_DIAMETER / 2)^2
    // 则在棋子圆形之内
    if ((center.x() - px) * (center.x() - px) + (center.y() - py) * (center.y() - py) >
        (BOARD_RECT_DIAMETER / 2) * (BOARD_RECT_DIAMETER / 2)) {
        return false;
    }
    return true;
}
// 判断棋子是否能够移动到指定位置
bool Board::canMove(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId) {
    if ((secondId != -1) && (pieces[selectId].red == pieces[secondId].red)) {
        return false;
    }
    // 判断指定类型的棋子是否能够移动到指定位置
    switch (pieces[selectId].type) {
    case PIECES_TYPE::CHE:
        return canMoveCHE(pieces, selectId, row, col, secondId);
    case PIECES_TYPE::BING:
        return canMoveBING(pieces, selectId, row, col, secondId);
    case PIECES_TYPE::JIANG:
        return canMoveJIANG(pieces, selectId, row, col, secondId);
    case PIECES_TYPE::MA:
        return canMoveMA(pieces, selectId, row, col, secondId);
    case PIECES_TYPE::PAO:
        return canMovePAO(pieces, selectId, row, col, secondId);
    case PIECES_TYPE::SHI:
        return canMoveSHI(pieces, selectId, row, col, secondId);
    case PIECES_TYPE::XIANG:
        return canMoveXIANG(pieces, selectId, row, col, secondId);
    default:
        return false;
    }
}
bool Board::canMoveCHE(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId) {
    // 获取前后的行差量和列分量
    const int dis_row = row - pieces[selectId].row;
    const int dis_col = col - pieces[selectId].col;
    if (dis_row && dis_col) {
        return false;
    }
    // 确保原先行到点击的位置之间不存在棋子
    for (int i = 0; i < PIECES_NUM; i++) {
        if (pieces[i].dead) {
            continue;
        }
        if (dis_row) {
            // 如果棋子和目标位置列不一样则跳过, 遍历到选中的棋子和目标棋子也跳过
            if (pieces[i].col != col || pieces[i].id == selectId || pieces[i].id == secondId) {
                continue;
            }
            // 如果遍历到的棋子和选中的棋子以及目标位置的距离相加等于选中的棋子和目标位置的距离则说明棋子位于中间
            if ((abs(pieces[i].row - row) + abs(pieces[i].row - pieces[selectId].row)) == abs(dis_row)) {
                return false;
            }
        } else {
            // 如果棋子和目标位置列不一样则跳过, 遍历到选中的棋子和目标棋子也跳过
            if (pieces[i].row != row || pieces[i].id == selectId || pieces[i].id == secondId) {
                continue;
            }
            // 如果遍历到的棋子和选中的棋子以及目标位置的距离相加等于选中的棋子和目标位置的距离则说明棋子位于中间
            if ((abs(pieces[i].col - col) + abs(pieces[i].col - pieces[selectId].col)) == abs(dis_col)) {
                return false;
            }
        }
    }
    return true;
}
bool Board::canMoveBING(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId) {
    const int dis_row = row - pieces[selectId].row;
    const int dis_col = col - pieces[selectId].col;
    const int abs_dis_row = abs(dis_row);
    const int abs_dis_col = abs(dis_col);
    // 兵每次只能走一格
    if (!moveOneGrid(pieces[selectId].row, pieces[selectId].col, row, col)) {
        return false;
    }
    // 确定前进方向
    const int forwardDir = getforwardDirOfBing(pieces[selectId]);

    if (isCrossedRiver(pieces[selectId])) {
        // 已过河：可以前进或左右移动，不能后退
        return (dis_row == forwardDir && dis_col == 0) ||
            (dis_row == 0 && abs_dis_col == 1);
    }
    else {
        // 未过河：只能前进
        return dis_row == forwardDir && dis_col == 0;
    }
    return false;
}
bool Board::canMoveJIANG(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId) {
    // 确保将和帅在九宫格内
    if ((row > 2 && row < 7) || col < 3 || col > 5) {
        return false;
    }
    // 获取前后的行差量和列分量
    const int dis_row = row - pieces[selectId].row;
    const int dis_col = col - pieces[selectId].col;
    const int dis = abs(dis_row) * 10 + abs(dis_col);
    // dis为10则说明行移动一步, dis为1说明列移动一步
    if (dis == 10 || dis == 1) {
        return true;
    }
    return false;
}
bool Board::canMoveMA(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId) {
    // 获取前后的行差量和列分量
    const int dis_row = row - pieces[selectId].row;
    const int dis_col = col - pieces[selectId].col;
    const int dis = abs(dis_row) * 10 + abs(dis_col);
    // 20 + 1 = 21  10 + 2 = 12
    if (dis == 21 || dis == 12) {
        const int blockRow = abs(dis_row) == 2 ? (pieces[selectId].row + dis_row / 2) : 
            pieces[selectId].row;
        const int blockCol = abs(dis_row) == 2 ? pieces[selectId].col : 
            (pieces[selectId].col + dis_col / 2);
        // 如果【马】被卡住马脚则走不了
        if (getPieceId(blockRow, blockCol) != -1) {
            return false;
        }
        return true;
    }
    return false;
}
bool Board::canMovePAO(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId) {
    // 获取前后的行差量和列分量
    const int dis_row = row - pieces[selectId].row;
    const int dis_col = col - pieces[selectId].col;
    if (dis_row && dis_col) {
        return false;
    }
    int midCount = 0;
    // 确保原先行到点击的位置之间不存在棋子
    for (int i = 0; i < PIECES_NUM; i++) {
        if (pieces[i].dead) {
            continue;
        }
        if (dis_row) {
            // 如果棋子和目标位置列不一样则跳过, 遍历到选中的棋子和目标棋子也跳过
            if (pieces[i].col != col || pieces[i].id == selectId || pieces[i].id == secondId) {
                continue;
            }
            // 如果遍历到的棋子和选中的棋子以及目标位置的距离相加等于选中的棋子和目标位置的距离则说明棋子位于中间
            if ((abs(pieces[i].row - row) + abs(pieces[i].row - pieces[selectId].row)) == abs(dis_row)) {
                midCount++;
            }
        } else {
            // 如果棋子和目标位置列不一样则跳过, 遍历到选中的棋子和目标棋子也跳过
            if (pieces[i].row != row || pieces[i].id == selectId || pieces[i].id == secondId) {
                continue;
            }
            // 如果遍历到的棋子和选中的棋子以及目标位置的距离相加等于选中的棋子和目标位置的距离则说明棋子位于中间
            if ((abs(pieces[i].col - col) + abs(pieces[i].col - pieces[selectId].col)) == abs(dis_col)) {
                midCount++;
            }
        }
    }
    if (secondId != -1 && midCount == 1) {
        return true;
    }
    if (secondId == -1 && midCount == 0) {
        return true;
    }
    return false;
}
bool Board::canMoveSHI(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId) {
    // 确保士在九宫格内
    if ((row > 2 && row < 7) || col < 3 || col > 5) {
        return false;
    }
    // 获取前后的行差量和列分量
    const int dis_row = row - pieces[selectId].row;
    const int dis_col = col - pieces[selectId].col;
    const int dis = abs(dis_row) * 10 + abs(dis_col);
    if (dis == 11) {
        return true;
    }
    return false;
}
bool Board::canMoveXIANG(ChessPieces pieces[PIECES_NUM], int selectId, int row, int col, int secondId) {
    // 确保【相】不能过河
    if (isCrossedRiver(pieces[selectId], row)) {
        return false;
    }
    const int dis_row = row - pieces[selectId].row;
    const int dis_col = col - pieces[selectId].col;
    const int dis = abs(dis_row) * 10 + abs(dis_col);
    if (dis == 22) {
        const int centerRow = (row + pieces[selectId].row) / 2;
        const int centerCol = (col + pieces[selectId].col) / 2;
        if (getPieceId(centerRow, centerCol) != -1) {
            return false;
        }
        return true;
    }
    return false;
}



// 画棋盘
void Board::drawBoard(QPainter &painter) {
    // 画十条横线
    for (int lineNum = 0; lineNum < BOARD_ROW_NUM; ++lineNum) {
        // point1(左偏移, 行号 * 棋盘格直径 + 上偏移)  point2((列总数 - 1) * 棋盘格直径 + 左偏移, 行号 * 棋盘格直径 + 上偏移)
        painter.drawLine(QPoint(BOARD_LEFT_OFFSET,
                                lineNum * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET),
                         QPoint((BOARD_COL_NUM - 1) * BOARD_RECT_DIAMETER + BOARD_LEFT_OFFSET,
                                lineNum * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET));
    }

    // 画九条竖线
    for (int colNum = 0; colNum < BOARD_COL_NUM; ++colNum) {
        if(colNum == 0 || colNum == (BOARD_COL_NUM - 1)) {
            // point1(左偏移 + 列号 * 棋盘格直径, 上偏移)
            // point2(列号 * 棋盘格直径 + 左偏移, (行总数 - 1) * 棋盘格直径 + 上偏移)
            painter.drawLine(QPoint(BOARD_LEFT_OFFSET + colNum * BOARD_RECT_DIAMETER,
                                    BOARD_TOP_OFFSET),
                             QPoint(colNum * BOARD_RECT_DIAMETER + BOARD_LEFT_OFFSET,
                                    (BOARD_ROW_NUM - 1) * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET));
        } else {
            // point1(左偏移 + 列号 * 棋盘格直径, 上偏移)
            // point2(列号 * 棋盘格直径 + 左偏移, (行总数 - 1 - 1) / 2 * 棋盘格直径 + 上偏移)
            painter.drawLine(QPoint(BOARD_LEFT_OFFSET + colNum * BOARD_RECT_DIAMETER,
                                    BOARD_TOP_OFFSET),
                             QPoint(colNum * BOARD_RECT_DIAMETER + BOARD_LEFT_OFFSET,
                                    (BOARD_ROW_NUM - 1 - 1) / 2 * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET));
            // point1(左偏移 + 列号 * 棋盘格直径, ((行总数 - 1 - 1) / 2 + 1) + 上偏移)
            // point2(列号 * 棋盘格直径 + 左偏移, (行总数 - 1) * 棋盘格直径 + 上偏移)
            painter.drawLine(QPoint(BOARD_LEFT_OFFSET + colNum * BOARD_RECT_DIAMETER,
                                    ((BOARD_ROW_NUM - 1 - 1) / 2 + 1) * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET),
                             QPoint(colNum * BOARD_RECT_DIAMETER + BOARD_LEFT_OFFSET,
                                    (BOARD_ROW_NUM - 1) * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET));
        }
    }
    // 画九宫格
    // point1(左偏移 + 3 * 棋盘格直径, 上偏移)
    // point2(左偏移 + 5 * 棋盘格直径, 上偏移 + 2 * 棋盘格直径)
    painter.drawLine(QPoint(BOARD_LEFT_OFFSET + 3 * BOARD_RECT_DIAMETER,
                            BOARD_TOP_OFFSET),
                     QPoint(5 * BOARD_RECT_DIAMETER + BOARD_LEFT_OFFSET,
                            2 * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET));
    // point1(左偏移 + 5 * 棋盘格直径, 上偏移)
    // point2(左偏移 + 3 * 棋盘格直径, 上偏移 + 2 * 棋盘格直径)
    painter.drawLine(QPoint(BOARD_LEFT_OFFSET + 5 * BOARD_RECT_DIAMETER,
                            BOARD_TOP_OFFSET),
                     QPoint(3 * BOARD_RECT_DIAMETER + BOARD_LEFT_OFFSET,
                            2 * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET));
    // point1(左偏移 + 3 * 棋盘格直径, 7 * 棋盘格直径 + 上偏移)
    // point2(左偏移 + 5 * 棋盘格直径, 上偏移 + 9 * 棋盘格直径)
    painter.drawLine(QPoint(BOARD_LEFT_OFFSET + 3 * BOARD_RECT_DIAMETER,
                            7 * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET),
                     QPoint(5 * BOARD_RECT_DIAMETER + BOARD_LEFT_OFFSET,
                            9 * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET));
    // point1(左偏移 + 5 * 棋盘格直径, 7 * 棋盘格直径 + 上偏移)
    // point2(左偏移 + 3 * 棋盘格直径, 上偏移 + 9 * 棋盘格直径)
    painter.drawLine(QPoint(BOARD_LEFT_OFFSET + 5 * BOARD_RECT_DIAMETER,
                            7 * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET),
                     QPoint(3 * BOARD_RECT_DIAMETER + BOARD_LEFT_OFFSET,
                            9 * BOARD_RECT_DIAMETER + BOARD_TOP_OFFSET));
}
// 画棋子
void Board::drawPiece(QPainter &painter, int id) {
    if (pieces[id].dead) {
        return;
    }
    // 设置画刷(背景)
    painter.setBrush(QBrush(id == selectId ? Qt::gray : Qt::yellow));
    // 设置画笔颜色
    painter.setPen(pieces[id].red ? Qt::red : Qt::black);
    // 画棋子圆盘
    painter.drawEllipse(pieceCenter(id),
                        BOARD_RECT_DIAMETER / 2, BOARD_RECT_DIAMETER / 2);
    // 设置字体
    painter.setFont(QFont("Microsoft YaHei", BOARD_RECT_DIAMETER / 2, 700));
    // 画棋子文字
    painter.drawText(pieceRect(id), pieces[id].getText(), QTextOption(Qt::AlignCenter));
}
// 根据棋子行和列返回棋盘行列对应的坐标
QPoint Board::pieceCenter(int row, int col) {
    // x(左偏移 + col * 棋盘格直径)
    // y(上偏移 + row * 棋盘格直径)
    return QPoint(BOARD_LEFT_OFFSET + col * BOARD_RECT_DIAMETER,
                  BOARD_TOP_OFFSET + row * BOARD_RECT_DIAMETER);
}
// 根据棋子id返回棋盘行列对应的坐标
QPoint Board::pieceCenter(int id) {
    return pieceCenter(pieces[id].row, pieces[id].col);
}
// 根据棋子获取棋子矩形
QRect Board::pieceRect(int id) {
    // point1(center.x - 棋盘格直径 / 2, center.y - 棋盘格直径 / 2)
    // point2(center.x + 棋盘格直径 / 2, center.y + 棋盘格直径 / 2)
    QPoint center = pieceCenter(id);
    return QRect(QPoint(center.x() - BOARD_RECT_DIAMETER / 2, center.y() - BOARD_RECT_DIAMETER / 2),
                 QPoint(center.x() + BOARD_RECT_DIAMETER / 2, center.y() + BOARD_RECT_DIAMETER / 2));
}

// 执行悔棋
// 为false指回退黑棋一步
// 为true指回退红棋一步
void Board::executeRetrack(bool isRed) {
    QSharedPointer<Step> s;
    if (isRed && !redSteps.empty()) {
        s = redSteps.takeLast();
    }
    else if (!isRed && !blackSteps.empty()) {
        s = blackSteps.takeLast();
    }
    if (!s) {
        return;
    }
    pieces[s->fromId].row = s->fromRow;
    pieces[s->fromId].col = s->fromCol;
    if (s->toId != -1) {
        pieces[s->toId].dead = false;
    }
}

void Board::checkGameEnd() {
    // 1. 检查将/帅是否被吃
    bool redGeneralAlive = false;
    bool blackGeneralAlive = false;

    for (int i = 0; i < PIECES_NUM; ++i) {
        if (pieces[i].dead) continue;
        if (pieces[i].type == PIECES_TYPE::JIANG) {
            pieces[i].red ? redGeneralAlive = true : blackGeneralAlive = true;
        }
    }

    if (!redGeneralAlive) {
        emit gameOver(GameResult::BlackWin);
        return;
    }
    if (!blackGeneralAlive) {
        emit gameOver(GameResult::RedWin);
        return;
    }

    // 2. 检查将帅是否面对面（特殊情况）
    if (isGeneralFacingEachOther()) {
        emit gameOver(isRedTurn ? GameResult::RedWin : GameResult::BlackWin);
        return; // 当前行棋方违规输
    }

    // 3. 检查当前行棋方是否被将军且无合法走法(困毙)
    if (isCheckmate(isRedTurn)) {
        emit gameOver(isRedTurn ? GameResult::BlackWin : GameResult::RedWin);
        return;
    }

    // 4. 检查当前行棋方是否无合法走法(困毙但未被将军)
    if (isStalemate(isRedTurn)) {
        emit gameOver(GameResult::Draw);
        return;
    }

    // 5. 检查重复局面(长将/长捉)
    if (isRepetitionDraw()) {
        emit gameOver(GameResult::Draw);
        return;
    }

    // 6. 检查剩余子力是否足以将死
    if (isMaterialDraw()) {
        emit gameOver(GameResult::Draw);
        return;
    }

    return;
}
// 双方的将是否会面对面
bool Board::isGeneralFacingEachOther() const {
    int redRow = -1, redCol = -1;
    int blackRow = -1, blackCol = -1;

    // 查找将帅位置
    for (int i = 0; i < PIECES_NUM; ++i) {
        if (pieces[i].type != PIECES_TYPE::JIANG || pieces[i].dead) continue;

        if (pieces[i].red) {
            redRow = pieces[i].row;
            redCol = pieces[i].col;
        }
        else {
            blackRow = pieces[i].row;
            blackCol = pieces[i].col;
        }
    }

    // 将帅在同一列且中间无遮挡
    if (redCol == blackCol) {
        int startRow = qMin(redRow, blackRow) + 1;
        int endRow = qMax(redRow, blackRow);

        bool hasPiece = false;
        for (int row = startRow; row < endRow; ++row) {
            for (int i = 0; i < PIECES_NUM; ++i) {
                if (!pieces[i].dead && pieces[i].row == row && pieces[i].col == redCol) {
                    hasPiece = true;
                    break;
                }
            }
        }
        if (!hasPiece) return true; // 中间无棋子遮挡
    }

    return false;
}

// 检查对方的棋子是否可以攻击到将/帅
bool Board::inspectOtherCheckJiang(ChessPieces pieces[PIECES_NUM], bool isRed) {
    int generalId = -1;
    for (int i = 0; i < PIECES_NUM; ++i) {
        // 找到行棋方的将
        if (!pieces[i].dead && pieces[i].type == PIECES_TYPE::JIANG && pieces[i].red == isRed) {
            generalId = i;
            break;
        }
    }
    // 检查将军是否被攻击
    bool inCheck = false;
    for (int i = 0; i < PIECES_NUM; ++i) {
        // 检查对方的棋子是否可以攻击到将/帅
        if (!pieces[i].dead && pieces[i].red != isRed) {
            if ((generalId != -1) &&
                canMove(pieces, i, pieces[generalId].row, pieces[generalId].col, generalId)) {

                inCheck = true;
                break;
            }
        }
    }
    return inCheck;
}



// 检查是否被绝杀
bool Board::isCheckmate(bool isRed) {
    // 如果攻击不到将，返回
    if (!inspectOtherCheckJiang(pieces, isRed)) return false;

    // 2. 检查是否有合法走法解救将军
    ChessPieces* tempPieces = copyChessPiecesArray(pieces);
    QVector<QSharedPointer<Step>> possibleSteps;
    generateAllPossibleSteps(possibleSteps, isRed, tempPieces);

    //printStepsFormatted(possibleSteps);

    // 遍历每一种走法，先走一步，再检查是否被将军
    // 如果存在一种走法不将军，则不是困死局面
    bool stillInCheck = true;
    for (const auto& step : possibleSteps) {
        simulateMove(step, tempPieces);

        if (!inspectOtherCheckJiang(tempPieces, isRed)) {
            stillInCheck = false;
        }
        undoMove(step, tempPieces);
    }

    delete tempPieces;
    tempPieces = nullptr;

    if (!stillInCheck) {
        return false; // 存在解除将军的走法
    }

    return true; // 所有走法都无法解除将军
}
// 无合法走法
bool Board::isStalemate(bool isRed) {
    QVector<QSharedPointer<Step>> possibleSteps;
    // isRed == isRedTurn
    // isRed == true ,则红方
    // isRed == false ,则黑方
    generateAllPossibleSteps(possibleSteps, isRed, pieces);
    return possibleSteps.isEmpty();
}
// 检查重复局面(长将/长捉)
bool Board::isRepetitionDraw() {
    // 简单实现：检查最近3次相同局面
    const int repeatCount = PERFECT_CHECK_NUM;
    if (moveHistory.size() < repeatCount * 2) return false;

    int lastIndex = moveHistory.size() - 1;
    quint64 currentHash = calculateBoardHash();
    int startIndex = lastIndex - repeatCount * 2 + 1;
    int repeats = 0;
    for (int i = lastIndex; i >= startIndex; i -= 2) { // 每隔两步检查
        if (moveHistory[i].boardHash == currentHash) {
            repeats++;
        }
    }
    if (repeats >= repeatCount) {
        return true;
    }
    return false;
}
// 检查剩余子力是否足以将死
bool Board::isMaterialDraw() {
    // 剩余子力不足的情况
    int redCount = 0, blackCount = 0;
    int redPower = 0, blackPower = 0;

    for (int i = 0; i < PIECES_NUM; ++i) {
        if (pieces[i].dead) continue;

        if (pieces[i].red) {
            redCount++;
            redPower += getPieceValue(pieces[i]);
        }
        else {
            blackCount++;
            blackPower += getPieceValue(pieces[i]);
        }
    }

    // 单将/帅
    if (redCount == 1 && blackCount == 1) return true;

    const int minPower = PIECE_WEIGHTS.value(PIECES_TYPE::XIANG) + 
        PIECE_WEIGHTS.value(PIECES_TYPE::JIANG);
    // 将帅+士/象
    if (redCount <= 2 && blackCount <= 2) {
        bool redLight = (redPower <= minPower); // 士或象的价值
        bool blackLight = (blackPower <= minPower);
        if (redLight && blackLight) return true;
    }

    return false;
}

// 辅助函数：计算棋盘哈希值
quint64 Board::calculateBoardHash() const {
    quint64 hash = 0;
    for (int i = 0; i < PIECES_NUM; ++i) {
        if (pieces[i].dead) continue;
        hash ^= (static_cast<quint64>(i) << (pieces[i].row * 8 + pieces[i].col));
    }
    hash ^= isRedTurn ? 1 : 0;
    return hash;
}

bool Board::moveOneGrid(int fromRow, int fromCol, int row, int col)
{
    const int dis_row = row - fromRow;
    const int dis_col = col - fromCol;
    const int abs_dis_row = abs(dis_row);
    const int abs_dis_col = abs(dis_col);
    // 每次只能走一格
    if ((abs_dis_row + abs_dis_col) == 1) {
        return true;
    }
    return false;
}

int Board::getPieceId(int row, int col) {
    // 检查目标位置是否有棋子
    int targetId = -1;
    for (int j = 0; j < PIECES_NUM; ++j) {
        if (!pieces[j].dead && pieces[j].row == row && pieces[j].col == col) {
            targetId = j;
            break;
        }
    }
    return targetId;
}

void Board::generateAllPossibleSteps(QVector<QSharedPointer<Step>>& steps,
    bool isMaximizingPlayer, ChessPieces pieces[PIECES_NUM]) {
    // isMaximizingPlayer == redTopBlackBottom
    for (int i = 0; i < PIECES_NUM; ++i) {
        // 如果棋子已经被吃, 跳过
        // 如果棋子类型不是最大化玩家的, 跳过
        if (pieces[i].dead || pieces[i].red != isMaximizingPlayer) continue;

        int row = pieces[i].row;
        int col = pieces[i].col;

        switch (pieces[i].type)
        {
        case PIECES_TYPE::CHE:
            // 直线移动，直到遇到障碍
            addStraightSteps(steps, i, pieces, row, col);
            break;
        case PIECES_TYPE::BING:
            generateBingPossibleSteps(steps, pieces[i], pieces);
            break;
        case PIECES_TYPE::JIANG:
            generateJiangPossibleSteps(steps, pieces[i], pieces);
            break;
        case PIECES_TYPE::MA:
            generateMaPossibleSteps(steps, pieces[i], pieces);
            break;
        case PIECES_TYPE::PAO:
            // 直线移动，吃子时需要跳过一个棋子
            addStraightSteps(steps, i, pieces, row, col, true);
            break;
        case PIECES_TYPE::SHI:
            generateShiPossibleSteps(steps, pieces[i], pieces);
            break;
        case PIECES_TYPE::XIANG:
            generateXiangPossibleSteps(steps, pieces[i], pieces);
            break;
        default:
            break;
        }
    }
}

void Board::generateJiangPossibleSteps(QVector<QSharedPointer<Step>>& steps, 
    const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]) {
    // 只能在九宫格内移动，每次一步
    int palaceMinRow = redTopBlackBottom ? (piece.red ? 0 : 7) : (piece.red ? 7 : 0);
    int palaceMaxRow = redTopBlackBottom ? (piece.red ? 2 : 9) : (piece.red ? 9 : 2);
    int palaceMinCol = 3;
    int palaceMaxCol = 5;

    int row = piece.row;
    int col = piece.col;
    int id = piece.id;

    // 检查四个方向
    checkAndAddStep(steps, id, row - 1, col, pieces, palaceMinRow, palaceMaxRow, palaceMinCol, palaceMaxCol);
    checkAndAddStep(steps, id, row + 1, col, pieces, palaceMinRow, palaceMaxRow, palaceMinCol, palaceMaxCol);
    checkAndAddStep(steps, id, row, col - 1, pieces, palaceMinRow, palaceMaxRow, palaceMinCol, palaceMaxCol);
    checkAndAddStep(steps, id, row, col + 1, pieces, palaceMinRow, palaceMaxRow, palaceMinCol, palaceMaxCol);
}

void Board::generateShiPossibleSteps(QVector<QSharedPointer<Step>>& steps,
    const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]) {
    // 只能在九宫格内移动，每次一步
    int palaceMinRow = redTopBlackBottom ? (piece.red ? 0 : 7) : (piece.red ? 7 : 0);
    int palaceMaxRow = redTopBlackBottom ? (piece.red ? 2 : 9) : (piece.red ? 9 : 2);
    int palaceMinCol = 3;
    int palaceMaxCol = 5;

    int row = piece.row;
    int col = piece.col;
    int id = piece.id;

    // 检查四个斜方向
    checkAndAddStep(steps, id, row - 1, col - 1, pieces, palaceMinRow,
        palaceMaxRow, palaceMinCol, palaceMaxCol);
    checkAndAddStep(steps, id, row - 1, col + 1, pieces, palaceMinRow,
        palaceMaxRow, palaceMinCol, palaceMaxCol);
    checkAndAddStep(steps, id, row + 1, col - 1, pieces, palaceMinRow,
        palaceMaxRow, palaceMinCol, palaceMaxCol);
    checkAndAddStep(steps, id, row + 1, col + 1, pieces, palaceMinRow,
        palaceMaxRow, palaceMinCol, palaceMaxCol);
}

void Board::generateXiangPossibleSteps(QVector<QSharedPointer<Step>>& steps,
    const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]) {
    int row = piece.row;
    int col = piece.col;
    // 田字移动，不能过河
    for (int dr = -2; dr <= 2; dr += 4) {
        for (int dc = -2; dc <= 2; dc += 4) {
            int newRow = row + dr;
            int newCol = col + dc;
            // 检查象眼是否被堵
            int eyeRow = row + dr / 2;
            int eyeCol = col + dc / 2;
            if (!isCrossedRiver(piece, newRow) &&
                newCol >= 0 && newCol <= 8 &&
                getPieceId(eyeRow, eyeCol) == -1) {
                checkAndAddStep(steps, piece.id, newRow, newCol, pieces);
            }
        }
    }
}

void Board::generateMaPossibleSteps(QVector<QSharedPointer<Step>>& steps,
    const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]) {
    int row = piece.row;
    int col = piece.col;
    // 日字移动，检查蹩马腿
    int dx[] = { -2, -1, 1, 2, 2, 1, -1, -2 };
    int dy[] = { 1, 2, 2, 1, -1, -2, -2, -1 };
    int legDx[] = { 0, -1, 0, 1, 1, 0, -1, 0 };
    int legDy[] = { 1, 0, 1, 0, 0, -1, 0, -1 };

    for (int k = 0; k < 8; ++k) {
        int newRow = row + dx[k];
        int newCol = col + dy[k];
        // 检查马腿是否被堵
        int legRow = row + legDx[k];
        int legCol = col + legDy[k];
        if (newRow >= 0 && newRow <= 9 && newCol >= 0 && newCol <= 8 &&
            getPieceId(legRow, legCol) == -1) {
            checkAndAddStep(steps, piece.id, newRow, newCol, pieces);
        }
    }
}

void Board::generateBingPossibleSteps(QVector<QSharedPointer<Step>>& steps,
    const ChessPieces& piece, ChessPieces pieces[PIECES_NUM]) {
    // 未过河只能前进，过河后可以左右移动
    checkAndAddStep(steps, piece.id, piece.row + getforwardDirOfBing(piece), piece.col, pieces);
    if (isCrossedRiver(piece)) {
        checkAndAddStep(steps, piece.id, piece.row, piece.col - 1, pieces);
        checkAndAddStep(steps, piece.id, piece.row, piece.col + 1, pieces);
    }
}

// 辅助函数：添加直线移动步骤（车和炮）
void Board::addStraightSteps(QVector<QSharedPointer<Step>>& steps, int pieceId, 
    ChessPieces pieces[PIECES_NUM], int row, int col, bool isCannon) {
    // 四个方向：上、下、左、右
    int dx[] = { -1, 1, 0, 0 };
    int dy[] = { 0, 0, -1, 1 };

    for (int k = 0; k < 4; ++k) {
        bool hasObstacle = false;
        for (int step = 1; step <= 9; ++step) {
            int newRow = row + dx[k] * step;
            int newCol = col + dy[k] * step;

            if (newRow < 0 || newRow > 9 || newCol < 0 || newCol > 8) break;

            int targetId = getPieceId(newRow, newCol);

            if (!isCannon) { // 车的移动规则
                if (targetId == -1) {
                    steps.append(QSharedPointer<Step>::create(
                        pieceId, row, col, newRow, newCol, targetId));
                }
                else {
                    if (canMove(pieces, pieceId, newRow, newCol, targetId)) {
                        steps.append(QSharedPointer<Step>::create(
                            pieceId, row, col, newRow, newCol, targetId));
                    }
                    break;
                }
            }
            else { // 炮的移动规则
                if (!hasObstacle) {
                    if (targetId == -1) {
                        steps.append(QSharedPointer<Step>::create(
                            pieceId, row, col, newRow, newCol, targetId));
                    }
                    else {
                        hasObstacle = true;
                    }
                }
                else {
                    if (targetId != -1) {
                        if (canMove(pieces, pieceId, newRow, newCol, targetId)) {
                            steps.append(QSharedPointer<Step>::create(
                                pieceId, row, col, newRow, newCol, targetId));
                        }
                        break;
                    }
                }
            }
        }
    }
}

// 辅助函数：检查并添加有效步骤
void Board::checkAndAddStep(QVector<QSharedPointer<Step>>& steps, int pieceId, int row, int col, 
    ChessPieces pieces[PIECES_NUM], int minRow, int maxRow, int minCol, int maxCol) {
    if (row >= minRow && row <= maxRow && col >= minCol && col <= maxCol) {
        int targetId = getPieceId(row, col);
        if (canMove(pieces, pieceId, row, col, targetId)) {
            steps.append(QSharedPointer<Step>::create(
                pieceId, pieces[pieceId].row, pieces[pieceId].col, row, col, targetId));
        }
    }
}

ChessPieces* Board::copyChessPiecesArray(
    const ChessPieces pieces[PIECES_NUM]) const {
    // 创建并管理数组
    ChessPieces* managedPieces = new ChessPieces[PIECES_NUM];
    std::copy(pieces, pieces + PIECES_NUM, managedPieces);
    return managedPieces;
}

void Board::simulateMove(QSharedPointer<Step> step, ChessPieces pieces[PIECES_NUM]) {
    if (step->toId != -1) {
        pieces[step->toId].dead = true;
    }

    // 移动棋子
    pieces[step->fromId].row = step->toRow;
    pieces[step->fromId].col = step->toCol;

    // 切换回合
    isRedTurn = !isRedTurn;
}
void Board::undoMove(QSharedPointer<Step> step, ChessPieces pieces[PIECES_NUM]) {
    // 恢复被吃掉的棋子
    if (step->toId != -1) {
        pieces[step->toId].dead = false;
    }

    // 恢复棋子位置
    pieces[step->fromId].row = step->fromRow;
    pieces[step->fromId].col = step->fromCol;

    // 恢复回合
    isRedTurn = !isRedTurn;
}

void Board::handleGameOver(GameResult res) {
    switch (res)
    {
    case GameResult::NoResult:
        break;
    case GameResult::RedWin:
        showResultBox(GameResult::RedWin);
        break;
    case GameResult::BlackWin:
        showResultBox(GameResult::BlackWin);
        break;
    case GameResult::Draw:
        showResultBox(GameResult::Draw);
        break;
    default:
        break;
    }
}
void Board::showResultBox(GameResult res) {
    isGameOver = true;
    setStyleSheet(R"(
    /* 主对话框样式 - 彩虹渐变背景 */
    QMessageBox {
        background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                                  stop:0 #FF9AA2, stop:0.25 #FFB7B2,
                                  stop:0.5 #FFDAC1, stop:0.75 #E2F0CB,
                                  stop:1 #B5EAD7);
        border-radius: 15px;
        border: 2px solid #FFFFFF;
        font-family: "Microsoft YaHei";
        min-width: 320px;
    }

    /* 标题样式 */
    QMessageBox QLabel#qt_msgbox_label {
        color: #5E2B97;
        font-size: 18px;
        font-weight: bold;
        padding: 15px 20px 5px;
    }

    /* 内容文字样式 */
    QMessageBox QLabel#qt_msgbox_label[text] {
        color: #2D3250;
        font-size: 15px;
        padding: 0 20px 15px;
    }

    /* 按钮容器样式 */
    QMessageBox QDialogButtonBox {
        padding: 0 20px 15px;
    }

    /* 按钮基础样式 */
    QMessageBox QPushButton {
        background: rgba(255,255,255,0.85);
        border: 1px solid rgba(255,255,255,0.9);
        border-radius: 8px;
        color: #5E2B97;
        font-size: 14px;
        min-width: 90px;
        padding: 8px 20px;
        margin: 0 8px;
    }

    /* 按钮悬停效果 */
    QMessageBox QPushButton:hover {
        background: rgba(255,255,255,0.95);
        border-color: #FFFFFF;
        color: #3A1078;
    }

    /* 按钮按下效果 */
    QMessageBox QPushButton:pressed {
        background: rgba(255,255,255,0.7);
    }

    /* 图标区域调整 */
    QMessageBox QLabel#qt_msgboxex_icon_label {
        padding-left: 25px;
    }

    /* 添加内阴影增强层次 */
    QMessageBox QFrame {
        background: transparent;
        border-radius: 15px;
    }
)");
    QMessageBox msgBox(this);
    msgBox.setWindowTitle("游戏结束");
    switch (res)
    {
	case GameResult::RedWin:
		msgBox.setText("红方获胜！");
		break;
	case GameResult::BlackWin:
		msgBox.setText("黑方获胜！");
		break;
	case GameResult::Draw:
		msgBox.setText("平局！");
		break;
	default:
		break;
	}

    // 设置中文按钮
    QPushButton* confirmBtn = msgBox.addButton("返回菜单", QMessageBox::YesRole);
    QPushButton* cancelBtn = msgBox.addButton("观察棋局", QMessageBox::NoRole);

    // 设置按钮样式（覆盖全局设置中的特定按钮）
    confirmBtn->setStyleSheet(
        "background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
        "stop:0 #FF6B6B, stop:1 #FF8E8E);"
        "color: white;"
        "font-weight: bold;"
    );

    cancelBtn->setStyleSheet(
        "background: rgba(255,255,255,0.9);"
        "color: #5E2B97;"
    );

    // 显示对话框
    msgBox.exec();
    if (msgBox.clickedButton() == confirmBtn) {
        emit requestReturnToMainMenu();
    }
}

QString Board::stepToString(const QSharedPointer<Step>& step) {
    return QString("From ID %1 (%2,%3) -> (%4,%5) [Capture ID: %6]")
        .arg(step->fromId)
        .arg(step->fromRow)
        .arg(step->fromCol)
        .arg(step->toRow)
        .arg(step->toCol)
        .arg(step->toId);
}

void Board::printStepsFormatted(const QVector<QSharedPointer<Step>>& steps) {
    qDebug() << "Possible moves (" << steps.size() << "):";
    qDebug() << "--------------------------------";
    for (const auto& step : steps) {
        qDebug() << stepToString(step).toStdString().c_str();
    }
    qDebug() << "--------------------------------";
}

void Board::printChessPieces(ChessPieces* pieces) {
    qDebug() << "Chess Pieces (" << PIECES_NUM << "):";
    qDebug() << "--------------------------------------------------";
    qDebug() << "ID  | Type      | Color | Pos  | Dead | RedTop";
    qDebug() << "--------------------------------------------------";

    for (int i = 0; i < PIECES_NUM; ++i) {
        const ChessPieces& piece = pieces[i];
        qDebug() << QString("%1 | %2 | %3 | (%4,%5) | %6 | %7")
            .arg(piece.id, 3)
            .arg(piece.getText())
            .arg(piece.red ? "Red" : "Black", -6)
            .arg(piece.row)
            .arg(piece.col)
            .arg(piece.dead ? "Yes" : "No", -5)
            .arg(piece.red ? "Yes" : "No");
    }
    qDebug() << "--------------------------------------------------";
}

